package cn.fayang.ymcc.service.impl;

import cn.fayang.ymcc.constant.util.AssertUtil;
import cn.fayang.ymcc.doc.CourseDoc;
import cn.fayang.ymcc.domain.*;
import cn.fayang.ymcc.dto.CourseDto;
import cn.fayang.ymcc.exception.GlobalException;
import cn.fayang.ymcc.feign.CourseSearchFeignClient;
import cn.fayang.ymcc.feign.MediaFileFeignClient;
import cn.fayang.ymcc.feing.StationMessageFeingCilent;
import cn.fayang.ymcc.mapper.CourseMapper;
import cn.fayang.ymcc.mq.StationMessageProducer;
import cn.fayang.ymcc.result.JSONResult;
import cn.fayang.ymcc.service.*;
import cn.fayang.ymcc.util.StrUtils;
import cn.fayang.ymcc.vo.CourseDetailVo;
import cn.fayang.ymcc.vo.CourseItemVo;
import cn.fayang.ymcc.vo.CourserOrderVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.lucene.store.SleepingLockWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import springfox.documentation.spring.web.json.Json;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author laoxiao
 * @since 2022-07-20
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
    @Autowired
    private ITeacherService teacherService;
    @Autowired
    private ICourseDetailService courseDetailService;
    @Autowired
    private ICourseResourceService courseResourceService;
    @Autowired
    private ICourseMarketService courseMarketService;
    @Autowired
    private ICourseTeacherService courseTeacherService;
    @Autowired
    private ICourseTypeService courseTypeService;
    @Autowired
    private ICourseSummaryService courseSummaryService;
    @Autowired
    private CourseSearchFeignClient courseSearchFeignClient;
    @Autowired
    private StationMessageProducer stationMessageProducer;
   @Autowired
   private StationMessageFeingCilent stationMessageFeingCilent;
   @Autowired
   private ICourseChapterService courseChapterService;
   @Autowired
   private MediaFileFeignClient mediaFileFeignClient;


    /**
     * 展示课程详情
     * @param courseId
     * @return
     */
    @Override
    public CourseDetailVo searchDetail(Long courseId) {
        //查询是否有此课程
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course,"请求无效");
        AssertUtil.isTrue(course.getStatus() == Course.STATE_OFFLINE ,"课程未上架");
        //课程销量
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        //课程统计
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        //课程详情
        CourseDetail courseDetail = courseDetailService.selectById(courseId);
        //查询老师
        Wrapper<CourseTeacher> teacherwarpper = new EntityWrapper<>();
        teacherwarpper.eq("course_id",courseId);
        List<CourseTeacher> courseTeachers = courseTeacherService.selectList(teacherwarpper);
        List<Long> teacherids = courseTeachers.stream().map(teacher -> teacher.getTeacherId()).collect(Collectors.toList());
        List<Teacher> teachers = teacherService.selectBatchIds(teacherids);
        //查询章节
        Wrapper<CourseChapter> ccwrapper = new EntityWrapper<>();
        ccwrapper.eq("course_id",courseId);
        List<CourseChapter> chapters = courseChapterService.selectList(ccwrapper);
        List<Long> chapterIds = chapters.stream().map(chapter -> chapter.getCourseId()).collect(Collectors.toList());
        String chapterStr = JSON.toJSONString(chapterIds);
        //调取接口查询视屏
        JSONResult jsonResult = mediaFileFeignClient.searchMediaFiles(chapterStr);
        //将查询到的视频准换位对象
        List<MediaFile> mediaFiles = new ArrayList<>();
        if(jsonResult.getData() != null){
           mediaFiles = JSONObject.parseArray(jsonResult.getData().toString(), MediaFile.class);
        }
        //将视屏放入章节中
        List<MediaFile> finalMediaFiles = mediaFiles;
        chapters.forEach(courseChapter -> courseChapter.getMediaFiles().addAll(finalMediaFiles));
        CourseDetailVo vo = new CourseDetailVo();
        vo.setCourse(course);
        vo.setCourseChapters(chapters);
        vo.setCourseMarket(courseMarket);
        vo.setCourseSummary(courseSummary);
        vo.setCourseDetail(courseDetail);
        vo.setTeachers(teachers);
        return vo;
    }


    /**
     * 返回订单展示页需要的数据
     * @param courseIds
     * @return
     */
    @Override
    public CourserOrderVo courseOrderInfo(String courseIds) {
        //将传回的ids通过工具类准换成list集合
        List<Long> ids = StrUtils.splitStr2LongArr(courseIds);
        Set<Long> setIds = ids.stream().collect(Collectors.toSet());
        //判断订单个数是否相同
        AssertUtil.isTrue(ids.size() == setIds.size(),"请求非法！");
        List<CourseItemVo> courseInfos = new ArrayList<>();
        BigDecimal totalAmount = new BigDecimal(0);
        for (Long id : setIds) {
            //封装课程和销售成 CourseItemVo
            Course course = selectById(id);
            //判断是否课程
            AssertUtil.isNotNull(course,"请求非法！");
            //判断课程是否上架
            boolean online = course.getStatus() == Course.STATE_OFFLINE;
            AssertUtil.isTrue(online,"请求非法！！");
            //判断是否有销售相关数据
            CourseMarket courseMarket = courseMarketService.selectById(id);
            AssertUtil.isNotNull(courseMarket,"请求非法！");
            //将数据封装进vo
            CourseItemVo courseItemVo = new CourseItemVo(course, courseMarket);
            courseInfos.add(courseItemVo);
            totalAmount = totalAmount.add(courseMarket.getPrice());
        }
        //返回前端需要的数据
        return new CourserOrderVo(courseInfos,totalAmount);



    }


    @Override
    @Transactional
    public void sava(CourseDto dto) {
        Course course = dto.getCourse();
        CourseDetail courseDetail = dto.getCourseDetail();
        CourseMarket courseMarket = dto.getCourseMarket();
        CourseResource courseResource = dto.getCourseResource();
        List<Long> teacharIds = dto.getTeacharIds();
        Course courseTmp = selectByName(course.getName());
        AssertUtil.isNull(courseTmp,"课程已被注册！！！");
        course.setStatus(Course.STATE_OFFLINE);
        course.setLoginId(1L);
        course.setLoginUserName("yhptest1");
        List<Teacher> teachers = teacherService.selectBatchIds(teacharIds);
        // 整成stream
        StringBuilder sb = new StringBuilder();
        teachers.forEach(teacher -> {
            sb.append(teacher.getName()).append(",");
        });
        course.setTeacherNames(sb.toString());
        insert(course);
        //* 保存课程详情
        saveCourseDetail(course, courseDetail);
        //* 保存课程销售
        saveCourseMarket(course, courseMarket);
        //* 保存课程讲师
        saveCourseTeacher(course, teacharIds);
        //* 保存课程资源
        saveCourseResource(course, courseResource);
        //* 初始化课程统计
        saveCourseSummary(course);
        //课程类型表中的课程数+1
        updateCourseType(course);

    }

    /**
     * 课程上架
     * @param courseId
     */
    @Override
    public void onLineCourse(Long courseId) {
        System.out.println(courseId);
        //根据id查询课程
            Course course = selectById(courseId);
            //判断课程是否存在
            AssertUtil.isNotNull(course,"课程不存在");
            //判断是否是下架状态
            boolean offLine = course.getStatus() == Course.STATE_ONLINE;
            AssertUtil.isTrue(offLine,"课程已经上架");
            //2.修改课程状态为上架，填写上架时间
            course.setStatus(1);
            course.setOnlineTime(new Date());
            updateById(course);
            //  3.3 使用feign远程调用search完成课程保存到Es中
            CourseType type = courseTypeService.selectById(course.getCourseTypeId());
            CourseMarket courseMarket = courseMarketService.selectById(courseId);
            CourseSummary courseSummary = courseSummaryService.selectById(courseId);
            CourseDoc doc = new CourseDoc();
            //设置需要保存到Es的字段
            BeanUtils.copyProperties(course,doc);
            BeanUtils.copyProperties(courseMarket,doc);

            BeanUtils.copyProperties(courseSummary,doc);

            doc.setCourseTypeName(type.getName());//这里要单独赋值
            String chargeName = courseMarket.getCharge() == 1 ? "免费" : "收费";
            doc.setChargeName(chargeName);
            JSONResult result = courseSearchFeignClient.saveCourse(doc);
            AssertUtil.isTrue(result.isSuccess(),"课程发布失败");
            /*String name = course.getName();
            MessageStation messageStation = new MessageStation();
            messageStation.setTitle("课程上架");
            messageStation.setContent("亲爱的用户,您发布的课程:"+name+"上架成功");
            messageStation.setType("系统消息");
            messageStation.setSendTime(new Date());
            // 用户id没做
            stationMessageProducer.sendMessage(messageStation);*/
    }

    /**
     * 课程下架
     * @param courseId
     */
    @Override
    public void offLineCourse(Long courseId) {
        //根据id查询课程
            Course course = selectById(courseId);
            //判断课程是否存在
            AssertUtil.isNotNull(course,"课程不存在");
            //判断是否是下架状态
            boolean offLine = course.getStatus() == Course.STATE_OFFLINE;
            AssertUtil.isTrue(offLine,"课程已经下架");
            //状态调整为下架
            course.setStatus(Course.STATE_OFFLINE);
            course.setEndTime(new Date());
            updateById(course);
            JSONResult result = courseSearchFeignClient.deleteCourse(course.getId());
            AssertUtil.isTrue(result.isSuccess(),"课程下架失败");
            String name = course.getName();
            MessageStation messageStation = new MessageStation();
            messageStation.setTitle("课程上架");
            messageStation.setContent("亲爱的用户,您发布的课程:"+name+"下架成功");
            messageStation.setType("系统消息");
            messageStation.setSendTime(new Date());

            throw new GlobalException("课程下架失败");

    }

    /**
     * 保存站内信
     * @param messageStation
     */
    @Override
    public JSONResult saveMessageStation(MessageStation messageStation) {
        stationMessageFeingCilent.saveOrUpdate(messageStation);
        return JSONResult.success();
    }



    /**
     * 课程类型表中的课程数+1
     * @param course
     */
    private void updateCourseType(Course course) {
        CourseType type = courseTypeService.selectById(course.getCourseTypeId());
        type.setTotalCount(type.getTotalCount() + 1);
        courseTypeService.updateById(type);
    }

    /**
     * 初始化课程统计
     * @param course
     */
    private void saveCourseSummary(Course course) {
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        courseSummaryService.insert(courseSummary);
    }

    /**
     * 保存课程资源
     * @param course
     * @param courseResource
     */
    private void saveCourseResource(Course course, CourseResource courseResource) {
        courseResource.setCourseId(course.getId());
        courseResourceService.insert(courseResource);
    }

    /**
     * 保存课程讲师
     * @param course
     * @param teacharIds
     */
    private void saveCourseTeacher(Course course, List<Long> teacharIds) {
        teacharIds.forEach(id->{
            CourseTeacher courseTeacher = new CourseTeacher();
            courseTeacher.setCourseId(course.getId());
            courseTeacher.setTeacherId(id);
            courseTeacherService.insert(courseTeacher);
        });
    }

    /**
     * 保存课程销售
     * @param course
     * @param courseMarket
     */
    private void saveCourseMarket(Course course, CourseMarket courseMarket) {
        courseMarket.setId(course.getId());
        courseMarketService.insert(courseMarket);
    }

    /**
     * 保存课程详情
     * @param course
     * @param courseDetail
     */
    private void saveCourseDetail(Course course, CourseDetail courseDetail) {
        courseDetail.setId(course.getId());
        courseDetailService.insert(courseDetail);
    }

    /**
     * 通过名字查询
     * @param name
     * @return
     */
    private Course selectByName(String name) {
        Wrapper<Course> tWrapper = new EntityWrapper<Course>();
        tWrapper.eq("name",name);
        return selectOne(tWrapper);
    }




}
